﻿using System;
using System.Collections.Generic;
using System.Linq.Expressions;
using System.Text;
using System.Threading.Tasks;
using Gmmy.DomainExtension;
using Gmmy.RepositoryExtension;
using Microsoft.Extensions.Logging;

namespace Gmmy.ApplicationExtension
{
    public abstract class BaseServices<T> : ProxyBaseService, IBaseServices<T>
        where T : class, new()
    {

        protected readonly IRepository<T, EntityList<T>> Repository;
        protected readonly BaseDbContext UnitOfWork;

        protected BaseServices(IRepository<T, EntityList<T>> repository, ILogger<object> logger = null) :base(logger)
        {
            this.Repository = repository;
            UnitOfWork = (BaseDbContext)repository.UnitOfWork;
        }
        #region 仓储
        /// <summary>
        /// 异步获取分页泛型实体(表达式排序,仅支持单一字段排序)
        /// </summary>
        /// <typeparam name="S"></typeparam>
        /// <param name="PageIndex"></param>
        /// <param name="PageSize"></param>
        /// <param name="specification"></param>
        /// <param name="orderByExpression"></param>
        /// <param name="IsDESC"></param>
        /// <param name="AsNoTracking"></param>
        /// <param name="thenByExpression"></param>
        /// <param name="configureAwait"></param>
        /// <returns></returns>
        public virtual async Task<EntityList<T>> FindAllAsync<S>(int PageIndex, int PageSize, ISpecification<T> specification, System.Linq.Expressions.Expression<Func<T, S>> orderByExpression, bool IsDESC, bool? AsNoTracking = true, List<SortParms<T>> thenByExpression = null)
        {
            return await this.Repository.FindAllAsync<S>(PageIndex, PageSize, specification, orderByExpression, IsDESC, AsNoTracking, thenByExpression);
        }
        /// <summary>
        /// 异步获取分页泛型实体(字典排序,支持多关键字排序)
        /// </summary>
        /// <typeparam name="S"></typeparam>
        /// <param name="PageIndex"></param>
        /// <param name="PageSize"></param>
        /// <param name="specification"></param>
        /// <param name="orderByExpression"></param>
        /// <param name="AsNoTracking"></param>
        /// <param name="thenByExpression"></param>
        /// <param name="configureAwait"></param>
        /// <returns></returns>
        public virtual async Task<EntityList<T>> FindAllAsync<S>(int PageIndex, int PageSize, ISpecification<T> specification, Dictionary<string, string> orderByExpression, bool? AsNoTracking = true, List<SortParms<T>> thenByExpression = null)
        {
            return await this.Repository.FindAllAsync<S>(PageIndex, PageSize, specification, orderByExpression, AsNoTracking, thenByExpression);
        }
        /// <summary>
        /// 异步获取所有整个泛型实体
        /// </summary>
        /// <param name="AsNoTracking"></param>
        /// <param name="configureAwait"></param>
        /// <returns></returns>
        public virtual async Task<IEnumerable<T>> GetAllAsync(bool? AsNoTracking = true)
        {
            return await this.Repository.GetAllAsync(AsNoTracking);
        }
        /// <summary>
        /// 异步获取部分泛型实体(规约查询)
        /// </summary>
        /// <param name="specification"></param>
        /// <param name="AsNoTracking"></param>
        /// <param name="configureAwait"></param>
        /// <returns></returns>
        public virtual async Task<IEnumerable<T>> GetManyAsync(ISpecification<T> specification, bool? AsNoTracking = true)
        {
            return await this.Repository.GetManyAsync(specification, AsNoTracking);
        }
        /// <summary>
        /// 异步获取TopN泛型实体(规约查询+表达式排序)
        /// </summary>
        /// <typeparam name="S"></typeparam>
        /// <param name="TopN"></param>
        /// <param name="specification"></param>
        /// <param name="orderByExpression"></param>
        /// <param name="IsDESC"></param>
        /// <param name="AsNoTracking"></param>
        /// <param name="thenByExpression"></param>
        /// <param name="configureAwait"></param>
        /// <returns></returns>
        public virtual async Task<IEnumerable<T>> GetListByTopNAsync<S>(int TopN, ISpecification<T> specification, System.Linq.Expressions.Expression<Func<T, S>> orderByExpression, bool IsDESC, bool? AsNoTracking = true, List<SortParms<T>> thenByExpression = null)
        {
            return await this.Repository.GetListByTopNAsync<S>(TopN, specification, orderByExpression, IsDESC, AsNoTracking, thenByExpression);
        }
        /// <summary>
        /// 异步获取单一实体(规约查询)
        /// </summary>
        /// <param name="specification"></param>
        /// <param name="AsNoTracking"></param>
        /// <param name="configureAwait"></param>
        /// <returns></returns>
        public virtual async Task<T> GetByConditionAsync(ISpecification<T> specification, bool? AsNoTracking = false)
        {
            return await this.Repository.GetByConditionAsync(specification, AsNoTracking);
        }
        /// <summary>
        /// 异步根据默认主键返回单一实体
        /// </summary>
        /// <param name="key"></param>
        /// <param name="configureAwait"></param>
        /// <returns></returns>
        public virtual async Task<T> GetByKeyAsync(object key)
        {
            return await this.Repository.GetByKeyAsync(key);
        }
        /// <summary>
        /// 异步添加一个实体并持久化
        /// </summary>
        /// <param name="entity"></param>
        /// <param name="configureAwait"></param>
        /// <returns></returns>
        public virtual async Task AddAsync(T entity)
        {
            this.Repository.Add(entity);
            await this.CommitAsync();
        }
        /// <summary>
        /// 异步批量添加实体并持久化
        /// </summary>
        /// <param name="entities"></param>
        /// <param name="configureAwait"></param>
        /// <returns></returns>
        public virtual async Task AddBatchAsync(IEnumerable<T> entities)
        {
            this.Repository.AddBatch(entities);
            await this.CommitAsync();
        }
        /// <summary>
        /// 异步更新一个实体(所有字段)并持久化
        /// </summary>
        /// <param name="entity"></param>
        /// <param name="configureAwait"></param>
        /// <returns></returns>
        public virtual async Task ModifyAsync(T entity)
        {
            this.Repository.Modify(entity);
            await this.CommitAsync();
        }
        /// <summary>
        /// 异步更新一个实体(按需字段)并持久化
        /// </summary>
        /// <param name="entity"></param>
        /// <param name="configureAwait"></param>
        /// <param name="properties"></param>
        /// <returns></returns>
        public async Task UpdateAsync(T entity, params Expression<Func<T, object>>[] properties)
        {
            this.Repository.Update(entity, properties);
            await this.CommitAsync();
        }
        /// <summary>
        /// 根据条件异步逻辑删除实体(确保存在IsDeleted字段)
        /// </summary>
        /// <param name="specification"></param>
        /// <param name="configureAwait"></param>
        /// <returns></returns>
        public async Task LogicDeleteAsync(ISpecification<T> specification)
        {
            this.Repository.LogicDelete(specification);
            await this.CommitAsync();
        }
        /// <summary>
        /// 异步物理删除单一实体
        /// </summary>
        /// <param name="entity"></param>
        /// <param name="configureAwait"></param>
        /// <returns></returns>
        public virtual async Task RemoveAsync(T entity)
        {
            this.Repository.Remove(entity);
            await this.CommitAsync();
        }
        /// <summary>
        /// 根据条件异步物理删除实体
        /// </summary>
        /// <param name="specification"></param>
        /// <param name="configureAwait"></param>
        /// <returns></returns>
        public virtual async Task RemoveAsync(ISpecification<T> specification)
        {
            this.Repository.Remove(specification);
            await this.CommitAsync();
        }
        /// <summary>
        /// 异步判断实体是否存在
        /// </summary>
        /// <param name="specification"></param>
        /// <param name="configureAwait"></param>
        /// <returns></returns>
        public virtual async Task<bool> ExistsAsync(ISpecification<T> specification)
        {
            return await this.Repository.ExistsAsync(specification);
        }
        /// <summary>
        /// 异步获取实体数量
        /// </summary>
        /// <param name="configureAwait"></param>
        /// <returns></returns>
        public async Task<int> GetCountAsync(bool configureAwait = true)
        {
            return await this.Repository.GetCountAsync(configureAwait);
        }
        /// <summary>
        /// 异步根据条件获取实体数量
        /// </summary>
        /// <param name="specification"></param>
        /// <param name="configureAwait"></param>
        /// <returns></returns>
        public async Task<int> GetCountAsync(ISpecification<T> specification)
        {
            return await this.Repository.GetCountAsync(specification);
        }

        #endregion

        #region 工作单元
        public async Task CommitAsync()
        {
            await UnitOfWork.SaveChangesAsync();
        }
        #endregion

    }
}
